package com.ruicar.afs.cloud.channel.channelworkflow.controller;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruicar.afs.cloud.channel.channelworkflow.condition.ChannelOnlineWorkFlowCondition;
import com.ruicar.afs.cloud.channel.channelworkflow.entity.WorkTaskAssign;
import com.ruicar.afs.cloud.channel.channelworkflow.entity.WorkTaskCreated;
import com.ruicar.afs.cloud.channel.channelworkflow.entity.WorkTaskDetail;
import com.ruicar.afs.cloud.channel.channelworkflow.service.WorkTaskApproveRecordService;
import com.ruicar.afs.cloud.channel.channelworkflow.service.WorkTaskAssignService;
import com.ruicar.afs.cloud.channel.channelworkflow.service.WorkTaskCreatedService;
import com.ruicar.afs.cloud.channel.channelworkflow.service.WorkTaskDetailService;
import com.ruicar.afs.cloud.channel.channelworkflow.vo.ChannelOnlineWorkTaskVo;
import com.ruicar.afs.cloud.channel.common.enums.ChannelAfsFlowEnum;
import com.ruicar.afs.cloud.channel.common.feign.ChannelUseCaseService;
import com.ruicar.afs.cloud.channel.common.until.ChannelConfig;
import com.ruicar.afs.cloud.channel.online.condition.ArchivesLogInfoCondition;
import com.ruicar.afs.cloud.channel.online.entity.ChannelBaseInfoTemp;
import com.ruicar.afs.cloud.channel.online.entity.ChannelQuotaInfoTemp;
import com.ruicar.afs.cloud.channel.online.entity.ChannelRiskInfoTemp;
import com.ruicar.afs.cloud.channel.online.service.ChannelArchivesInfoService;
import com.ruicar.afs.cloud.channel.online.service.ChannelOnlineService;
import com.ruicar.afs.cloud.channel.online.service.ChannelQuotaInfoService;
import com.ruicar.afs.cloud.channel.online.service.ChannelRiskInfoService;
import com.ruicar.afs.cloud.channel.online.vo.ChannelQuotaInfoVo;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.log.annotation.SysLog;
import com.ruicar.afs.cloud.common.core.security.util.SecurityUtils;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.WorkFlowResponse;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.QueryFLowCmdRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.TaskSubmitRequest;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.response.FlowCmdBean;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.math.BigDecimal;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.ruicar.afs.cloud.channel.online.untils.ChannelOnlineConstants.*;

/**
 * @author: sang jian
 * @date: 2020/8/24 15:45
 * @description:
 */

@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/channelQuotaWorkFlow")
@Api(value = "channelQuotaWorkFlow", description = "合作商额度维护工作流处理")
public class ChannelQuotaWorkflowController {

    private final WorkTaskAssignService workTaskAssignService;
    private final WorkTaskCreatedService workTaskCreatedService;
    private final WorkTaskDetailService workTaskDetailService;
    private final WorkTaskApproveRecordService workTaskApproveRecordService;
    private final WorkflowService workflowService;
    private final ChannelOnlineService channelOnlineService;
    private final ChannelRiskInfoService channelRiskInfoService;
    private final ChannelQuotaInfoService channelQuotaInfoService;
    private ChannelConfig channelConfig;
    private ChannelUseCaseService channelUseCaseService;
    private  ChannelArchivesInfoService channelArchivesInfoService;

    @PostMapping(value = "/getChannelQuotaTaskByCondition")
    @ApiOperation(value = "多条件获取渠道额度维护待办任务")
    public IResponse getChannelQuotaTaskByCondition(@RequestBody ChannelOnlineWorkFlowCondition condition) {
        Page page = new Page(condition.getPageNumber(), condition.getPageSize());
        //获取当前用户角色信息
        condition.setUserRoles(SecurityUtils.getRoles());
        IPage<ChannelOnlineWorkTaskVo> channelQuotaTasks = workTaskAssignService.getChannelQuotaTaskByCondition(page, condition);
        return IResponse.success(channelQuotaTasks);
    }

    @PostMapping(value = "/approveChannelQuotaWorkFlow")
    @ApiOperation(value = "提交合作商收款账号审批流程")
    @SysLog("提交合作商收款账号审批流程")
    @Transactional(rollbackFor = Exception.class)
    public IResponse approveChannelQuotaWorkFlow(@RequestBody ChannelOnlineWorkFlowCondition condition) throws JsonProcessingException {

        WorkTaskAssign assgin = workTaskAssignService.getOne(Wrappers.<WorkTaskAssign>query().lambda()
                .eq(WorkTaskAssign::getBizDataId, condition.getBizDataId()));
        WorkTaskCreated created = workTaskCreatedService.getOne(Wrappers.<WorkTaskCreated>query().lambda().eq(WorkTaskCreated::getBizDataId, condition.getBizDataId()));
        WorkTaskDetail detail = workTaskDetailService.getOne(Wrappers.<WorkTaskDetail>query().lambda().eq(WorkTaskDetail::getBizDataId, condition.getBizDataId()));

        //提交完成之后删除其他人员代办
        List<WorkTaskAssign> assignList = workTaskAssignService.list(Wrappers.<WorkTaskAssign>query().lambda().eq(WorkTaskAssign::getBizDataId, condition.getBizDataId()));
        //渠道id
        Long channelId = condition.getChannelId();
        //获取合作商基本信息
        ChannelBaseInfoTemp baseInfoTemp = channelOnlineService.getById(condition.getChannelId());
        TaskSubmitRequest taskSubmitRequest = new TaskSubmitRequest();
        taskSubmitRequest.setGwtUserId(assgin.getAssignId());
        taskSubmitRequest.setAfsFlowKey(created.getAfsFlowKey());
        taskSubmitRequest.setBizDataId(created.getBizDataId());
        QueryFLowCmdRequest request = new QueryFLowCmdRequest();
        request.setFlowInstanceId(created.getFlowInstanceId());
        WorkFlowResponse<List<FlowCmdBean>> cmdResponse = workflowService.queryFlowCmd(request);
        List<FlowCmdBean> cmdList = cmdResponse.getAfsData();
        FlowCmdBean cmd = workTaskCreatedService.channelApprove(condition.getApprove(), cmdList);

        if (cmd != null) {
            log.info("==================================提交工作流开始==================================》");
            taskSubmitRequest.setCmdId(cmd.getId());
            ObjectMapper mapper = new ObjectMapper();
            //获取配置节点信息
            String json = mapper.writeValueAsString(baseInfoTemp);
            JSONObject cancelJson = JSONObject.parseObject(json);
            if (BUSINESS_TYPE_NEW_CAR.equals(detail.getBusinessType())) {
                //新车业务类型
                cancelJson.put(AfsEnumUtil.key(ChannelAfsFlowEnum.BUSINESS_TYPE), BUSINESS_TYPE_NEW_CAR);
            } else if (BUSINESS_TYPE_OLD_CAR.equals(detail.getBusinessType())) {
                //二手车业务类型
                cancelJson.put(AfsEnumUtil.key(ChannelAfsFlowEnum.BUSINESS_TYPE), BUSINESS_TYPE_OLD_CAR);
            }
            workflowService.taskSubmit(taskSubmitRequest, cancelJson);
            workTaskApproveRecordService.approveSave(condition, cmd);
            log.info("==================================业务逻辑处理开始==================================》");
            String taskMemo = created.getTaskMemo();
            if (!StrUtil.isBlank(taskMemo)) {
                JSONObject jsonMemo = (JSONObject) JSONObject.parse(taskMemo);
                String memo = (String) jsonMemo.get(AfsEnumUtil.key(ChannelAfsFlowEnum.NODE_LABEL));
                if (AfsEnumUtil.desc(ChannelAfsFlowEnum.CHANNEL_BACK).equals(cmd.getCmdDis())) {
                    //首节点
                    if (FIRST_NODE.equals(memo)) {
                        //首节点(退回特殊处理逻辑)：退回
                        //新车二手车都走这个方法,清除调整值
                        refusedMethod(channelId,detail.getBusinessType());
                        workTaskDetailService.removeById(detail);
                        workTaskCreatedService.removeById(created);
                    }
                }
                if (AfsEnumUtil.desc(ChannelAfsFlowEnum.CHANNEL_REFUSE).equals(cmd.getCmdDis())) {
                    //首节点(退回特殊处理逻辑)//拒绝
                    //新车二手车都走这个方法,清除调整值
                    refusedMethod(channelId,detail.getBusinessType());
                }
                if (AfsEnumUtil.desc(ChannelAfsFlowEnum.CHANNEL_SUBMIT).equals(cmd.getCmdDis()) && END_NODE.equals(memo)) {
                    //  调用额度调整方法
                    passMethod(channelId,detail.getBusinessType());
                }
            }
            //删除剩余节点数据信息
            for (int i = 0; i < assignList.size(); i++) {
                workTaskAssignService.removeById(assignList.get(i).getId());
            }
            return IResponse.success("提交成功");
        } else {
            return IResponse.fail("提交失败,提交指令异常，请确认！");
        }

    }

    /*
    * 拒绝或首节点退回后额度处理公共方法
    *
    * */
    public void refusedMethod(Long channelId,String busType) {
        //channelId
        //busType
        //清除风控表调整字段值
        List<ChannelRiskInfoTemp> riskInfoTemps = channelRiskInfoService.list(Wrappers.<ChannelRiskInfoTemp>query().lambda()
                .eq(ChannelRiskInfoTemp::getChannelId, channelId)
                .eq(ChannelRiskInfoTemp::getBusinessType, busType)
        );
        riskInfoTemps.get(0).setMarginTune(null);
        channelRiskInfoService.updateById(riskInfoTemps.get(0));
        //清除额度表中各个调整字段的值
        List<ChannelQuotaInfoTemp> quotaInfoTemps = channelQuotaInfoService.list(Wrappers.<ChannelQuotaInfoTemp>query().lambda()
                .eq(ChannelQuotaInfoTemp::getChannelId, channelId)
                .eq(ChannelQuotaInfoTemp::getBusinessType, busType)
        );
        if(quotaInfoTemps.size() > 0){
            for (ChannelQuotaInfoTemp channelQuotaInfoTemp : quotaInfoTemps){
                //签放额度调整归零
                channelQuotaInfoTemp.setQuotaSigning(BigDecimal.ZERO);
                //临时额度调整归零
                channelQuotaInfoTemp.setTempQuotaAdjust(BigDecimal.ZERO);
                //临时额度有效期调整归零
                channelQuotaInfoTemp.setValidityTermEndAdjust(null);
                //额度是否控制调整归零
                channelQuotaInfoTemp.setQuotaControlSwitchAdjust(null);
            }
        }
        channelQuotaInfoService.updateBatchById(quotaInfoTemps);
    }

    /*
     * 审批通过之后额度处理公共方法
     *
     * */
    public void passMethod(Long channelId,String busType) {
        //channelId
        //busType
        //风控信息
        List<ChannelRiskInfoTemp> riskInfoTemps = channelRiskInfoService.list(Wrappers.<ChannelRiskInfoTemp>query().lambda()
                .eq(ChannelRiskInfoTemp::getChannelId, channelId)
                .eq(ChannelRiskInfoTemp::getBusinessType, busType)
        );
        ChannelRiskInfoTemp riskInfoTemp = riskInfoTemps.get(0);
        //额度信息
        List<ChannelQuotaInfoTemp> quotaInfoTemps = channelQuotaInfoService.list(Wrappers.<ChannelQuotaInfoTemp>query().lambda()
                .eq(ChannelQuotaInfoTemp::getChannelId, channelId)
                .eq(ChannelQuotaInfoTemp::getBusinessType, busType)
        );

        BigDecimal channelDeposit = riskInfoTemp.getChannelDeposit() == null ? BigDecimal.ZERO : riskInfoTemp.getChannelDeposit();
        BigDecimal marginTune = riskInfoTemp.getMarginTune() == null ? BigDecimal.ZERO : riskInfoTemp.getMarginTune();
        //最新保证金额=原始保证金+此次保证金调整金额
        riskInfoTemp.setChannelDeposit(channelDeposit.add(marginTune).setScale(2, BigDecimal.ROUND_HALF_UP));
        //新车保证金调整金额归零
        riskInfoTemp.setMarginTune(BigDecimal.ZERO);
        channelRiskInfoService.updateById(riskInfoTemp);
        //记录
        ArchivesLogInfoCondition logInfoCondition = new ArchivesLogInfoCondition();
        logInfoCondition.setChannelId(riskInfoTemp.getChannelId());
        logInfoCondition.setEventName(BUSINESS_TYPE_NEW_CAR.equals(busType) ? "新车" : "二手车" + "保证金应收金额调整");
        logInfoCondition.setDescription(BUSINESS_TYPE_NEW_CAR.equals(busType) ? "新车" : "二手车" + "保证金应收金额由" + channelDeposit +"调整为" + channelDeposit.add(marginTune).setScale(2, BigDecimal.ROUND_HALF_UP));
        channelArchivesInfoService.saveQuotaChangeArchivesInfo(logInfoCondition);

        log.info("==================================渠道新车签放额度信息逻辑处理开始==================================》");

        if(quotaInfoTemps.size() > 0){
            for (ChannelQuotaInfoTemp quotaInfoTemp : quotaInfoTemps){
                //签放额度调整
                BigDecimal quotaSigning =quotaInfoTemp.getQuotaSigning() == null ? BigDecimal.ZERO : quotaInfoTemp.getQuotaSigning();
                //临时额度调整
                BigDecimal tempQuotaAdjust =quotaInfoTemp.getTempQuotaAdjust() == null ? BigDecimal.ZERO : quotaInfoTemp.getTempQuotaAdjust();
                //原始签放额度金额
                BigDecimal quotaAmount = quotaInfoTemp.getQuotaAmount() == null ? BigDecimal.ZERO : quotaInfoTemp.getQuotaAmount();
                //原始占用额度金额
                BigDecimal occupiedQuota = quotaInfoTemp.getOccupiedQuota() == null ? BigDecimal.ZERO : quotaInfoTemp.getOccupiedQuota();

                BigDecimal tempQuota = quotaInfoTemp.getTempQuota() == null ? BigDecimal.ZERO : quotaInfoTemp.getTempQuota();

                //当前临时额度=临时额度调整
                quotaInfoTemp.setTempQuota(tempQuotaAdjust);
                //当前签放额度=数据库已有签放额度+此次追加签放额度
                quotaInfoTemp.setQuotaAmount(quotaAmount.add(quotaSigning).setScale(2, BigDecimal.ROUND_HALF_UP));
                //剩余额度=当前签放额度+当前临时额度-占用额度
                quotaInfoTemp.setSurplusQuota( quotaInfoTemp.getTempQuota().add(quotaInfoTemp.getQuotaAmount()).subtract(occupiedQuota).setScale(2, BigDecimal.ROUND_HALF_UP));
                //临时额度有效期调整为最新的
                quotaInfoTemp.setValidityTermEnd(quotaInfoTemp.getValidityTermEndAdjust());
                //临时额度有效期调整归零
                quotaInfoTemp.setValidityTermEndAdjust(null);
                //是否控制额度更新
                quotaInfoTemp.setQuotaControlSwitch(quotaInfoTemp.getQuotaControlSwitchAdjust());
                //是否控制额度调整归零
                quotaInfoTemp.setQuotaControlSwitchAdjust(null);
                //额度调整归零
                quotaInfoTemp.setTempQuotaAdjust(BigDecimal.ZERO);
                quotaInfoTemp.setQuotaSigning(BigDecimal.ZERO);
                //更新最新额度信息
                channelQuotaInfoService.updateById(quotaInfoTemp);
                /*记录到渠道日志信息中*/
                if( (quotaSigning == null ? BigDecimal.ZERO : quotaSigning).compareTo(BigDecimal.ZERO) != 0 || (tempQuotaAdjust == null ? BigDecimal.ZERO : tempQuotaAdjust).compareTo(tempQuota) != 0 ){
                    //临时额度调整和额度调整都不为0
                    channelQuotaInfoService.saveLog(quotaInfoTemp,quotaAmount);
                }
            }
        }
        //同步数据到案件服务
        ChannelQuotaInfoVo channelQuotaInfoVo = new ChannelQuotaInfoVo();
        channelQuotaInfoVo.setRiskInfo(riskInfoTemp);
        channelQuotaInfoVo.setQuota(quotaInfoTemps);
        Map<String, String> headers = new HashMap<String, String>();
        headers.put("clientId", channelConfig.getCaseClientId());
        headers.put("clientSecret", channelConfig.getCaseClientSecret());
        channelUseCaseService.upQuota(channelQuotaInfoVo,headers);
    }

}
